//
//  UserDefaultable.swift
//  Sports
//
//  Created by Maynard on 2017/4/19.
//  Copyright © 2017年 Maynard. All rights reserved.
//

import Foundation

// MARK: - Use

// Preparation

//用法示意
/*
 UserDefaults.Set.set("abc", forKey: .feedbackDraft)
 let string = UserDefaults.Set.string(forKey: .feedbackDraft)
 */

extension UserDefaults {
    
    struct Home: DoubleUserDefaultable, BoolUserDefaultable {
        enum DoubleDefaultKey: String {
            case seconds //计时器关联的时间戳
            case date //存储seconds计时器的日期
            case startDate //当日开始时间
            case lastShowSubscribtionDate //上次自动弹出订阅界面的时间
        }
        
        enum BoolDefaultKey: String {
            case maskShowed
        }
    }
    
    struct User: BoolUserDefaultable,StringUserDefaultable {
        ///订阅是否有效
        enum BoolDefaultKey : String {
            case isLogin
            case isFirst
        }
        enum  StringDefaultKey: String{
            case authorization            
        }
    }
    
    
//    struct Theme: BoolUserDefaultable {
//        enum BoolDefaultKey : String {
//            //是否够夜间模式
//            case isNight
//        }
//    }
//
//    //app 相关
//    struct Appalication: BoolUserDefaultable, StringUserDefaultable, IntegerUserDefaultable, DoubleUserDefaultable {
//        enum BoolDefaultKey : String {
//            //是否是第一次启动应用
//            case isFirstLoad
//            case shouldShowRateUs
//            case ipProtectSwitch
//            case isFirstDoubleClick
//            case setDefaultConfigFor142
//
//        }
//
//        enum StringDefaultKey : String {
//            //是否今天
//            case lastDayString
//
//        }
//
//        enum IntegerDefaultKey : String {
//            //连接成功次数
//            case connectSuccessNumber
//            case appOptionVersionNumber//APP建议更新版本号
//        }
//
//        enum DoubleDefaultKey: String {
//            case nextVerifySubscriptionDate
//        }
//    }
//    //设置相关
//    struct Share : BoolUserDefaultable {
//
//        private init() { }
//
//
//        enum BoolDefaultKey: String {
//            case isLoginFacebook
//        }
//    }
//
//
//    //设置相关
//    struct Set : StringUserDefaultable, BoolUserDefaultable,IntegerUserDefaultable {
//
//        private init() { }
//
//        enum IntegerDefaultKey: String {
//            ///双击涂色时是八个方向还是四个
//            case dirctions
//        }
//
//        enum StringDefaultKey : String {
//            //意见反馈草稿
//            case feedbackDraft
//            case userName
//
//        }
//
//        enum BoolDefaultKey: String {
//
//            ///放大镜是否可用
//            case magnifierDisable = "newMagnifierDisable"
//            ///自动锁定填色
//            case autoTargetDisable = "newAutoTargetDisable"
//            ///震动提示
//            case vibrationDisable = "newShockFeedbackDisable"
//            ///双击涂色
//            case doubleClickDisable = "newDoubleClickDisable"
//            ///夜间模式
//            case nightModelDisable = "NightNightThemeKey"
//
//            var index: Int{
//                switch self {
//                case .magnifierDisable:
//                    return 0
//                case .autoTargetDisable:
//                    return 1
//                case .vibrationDisable:
//                    return 2
//                case .doubleClickDisable:
//                    return 3
//                case .nightModelDisable:
//                    return 4
//                }
//            }
//        }
//    }
//
//
//    struct Recommend: IntegerUserDefaultable, StringUserDefaultable, BoolUserDefaultable {
//
//        enum IntegerDefaultKey: String {
//            /// lastPid上次喜欢图片ID 没有值传空
//            case lastPid
//        }
//
//        enum BoolDefaultKey: String {
//            case defaultIsRecommend// 预置的图片是否看过了
//        }
//
//        enum StringDefaultKey : String {
//            ///本地已经推荐过的
//            case exsitsPid
//        }
//    }
//
//    struct Server: StringUserDefaultable,BoolUserDefaultable {
//        enum StringDefaultKey : String {
//            case productArray
//        }
//
//        enum BoolDefaultKey: String {
//            case paymentCanceled// 支付页面取消支付后询问原因，只需要一次
//        }
//    }
//
//    struct Pay: BoolUserDefaultable, StringUserDefaultable {
//        enum BoolDefaultKey: String {
//            case cancelReasonShowed
//        }
//
//        enum StringDefaultKey: String {
//            case purchaseID //内购产品ID
//        }
//    }
}



protocol KeyNamespaceable { }

extension KeyNamespaceable {
    private static func namespace(_ key: String) -> String {
        return "\(Self.self).\(key)"
    }
    
    static func namespace<T: RawRepresentable>(_ key: T) -> String where T.RawValue == String {
        return namespace(key.rawValue)
    }
}


// MARK: - Bool Defaults

protocol BoolUserDefaultable : KeyNamespaceable {
    associatedtype BoolDefaultKey : RawRepresentable
}

extension BoolUserDefaultable where BoolDefaultKey.RawValue == String {
    
    // Set
    
    static func set(_ bool: Bool, forKey key: BoolDefaultKey) {
        let key = namespace(key)
        UserDefaults.standard.set(bool, forKey: key)
    }
    
    // Get
    
    static func bool(forKey key: BoolDefaultKey) -> Bool {
        let key = namespace(key)
        return UserDefaults.standard.bool(forKey: key)
    }
}


// MARK: - Float Defaults

protocol FloatUserDefaultable : KeyNamespaceable {
    associatedtype FloatDefaultKey : RawRepresentable
}

extension FloatUserDefaultable where FloatDefaultKey.RawValue == String {
    
    // Set
    
    static func set(_ float: Float, forKey key: FloatDefaultKey) {
        let key = namespace(key)
        UserDefaults.standard.set(float, forKey: key)
    }
    
    // Get
    
    static func float(forKey key: FloatDefaultKey) -> Float {
        let key = namespace(key)
        return UserDefaults.standard.float(forKey: key)
    }
}


// MARK: - Integer Defaults

protocol IntegerUserDefaultable : KeyNamespaceable {
    associatedtype IntegerDefaultKey : RawRepresentable
}

extension IntegerUserDefaultable where IntegerDefaultKey.RawValue == String {
    
    // Set
    
    static func set(_ integer: Int, forKey key: IntegerDefaultKey) {
        let key = namespace(key)
        UserDefaults.standard.set(integer, forKey: key)
    }
    
    // Get
    
    static func integer(forKey key: IntegerDefaultKey) -> Int {
        let key = namespace(key)
        return UserDefaults.standard.integer(forKey: key)
    }
}


// MARK: - Object Defaults

protocol ObjectUserDefaultable : KeyNamespaceable {
    associatedtype ObjectDefaultKey : RawRepresentable
}

extension ObjectUserDefaultable where ObjectDefaultKey.RawValue == String {
    
    // Set
    
    static func set(_ object: AnyObject, forKey key: ObjectDefaultKey) {
        let key = namespace(key)
        UserDefaults.standard.set(object, forKey: key)
    }
    
    // Get
    
    static func object(forKey key: ObjectDefaultKey) -> Any? {
        let key = namespace(key)
        return UserDefaults.standard.object(forKey: key)
    }
}


// MARK: - Double Defaults

protocol DoubleUserDefaultable : KeyNamespaceable {
    associatedtype DoubleDefaultKey : RawRepresentable
}

extension DoubleUserDefaultable where DoubleDefaultKey.RawValue == String {
    
    // Set
    
    static func set(_ double: Double, forKey key: DoubleDefaultKey) {
        let key = namespace(key)
        UserDefaults.standard.set(double, forKey: key)
    }
    
    // Get
    
    static func double(forKey key: DoubleDefaultKey) -> Double {
        let key = namespace(key)
        return UserDefaults.standard.double(forKey: key)
    }
}

protocol StringUserDefaultable : KeyNamespaceable {
    associatedtype StringDefaultKey : RawRepresentable
}

extension StringUserDefaultable where StringDefaultKey.RawValue == String {
    
    // Set
    
    static func set(_ string: String, forKey key: StringDefaultKey) {
        let key = namespace(key)
        UserDefaults.standard.set(string, forKey: key)
    }
    
    // Get
    
    static func string(forKey key: StringDefaultKey) -> String? {
        let key = namespace(key)
        return UserDefaults.standard.string(forKey: key)
    }
}



// MARK: - URL Defaults

protocol URLUserDefaultable : KeyNamespaceable {
    associatedtype URLDefaultKey : RawRepresentable
}

extension URLUserDefaultable where URLDefaultKey.RawValue == String {
    
    // Set
    
    static func set(_ url: URL, forKey key: URLDefaultKey) {
        let key = namespace(key)
        UserDefaults.standard.set(url, forKey: key)
    }
    
    // Get
    
    static func url(forKey key: URLDefaultKey) -> URL? {
        let key = namespace(key)
        return UserDefaults.standard.url(forKey: key)
    }
}


